package com.boatAnchorAssistant.service.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.boatAnchorAssistant.pojo.FinalValue;
import com.boatAnchorAssistant.pojo.entity.Department;
import com.boatAnchorAssistant.pojo.entity.DepartmentLinkmanMp;
import com.boatAnchorAssistant.pojo.entity.Role;
import com.boatAnchorAssistant.pojo.entity.User;
import com.boatAnchorAssistant.pojo.event.department.CreateDepartmentEvent;
import com.boatAnchorAssistant.pojo.event.department.DeleteDepartmentEvent;
import com.boatAnchorAssistant.pojo.param.department.*;
import com.boatAnchorAssistant.pojo.vo.department.*;
import com.boatAnchorAssistant.pojo.dto.department.*;
import com.boatAnchorAssistant.service.repository.in.*;
import com.boatAnchorAssistant.service.service.in.DepartmentService;
import nirvana.core.domains.vo.PageResult;
import nirvana.core.exceptions.BizException;
import nirvana.core.utils.ids.IdGenerator;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 【描 述】：部门服务
 * 【环 境】：J2SE 17
 * 【详 细】：
 *
 */
@Service
public class DepartmentServiceImpl implements DepartmentService {

    private final DepartmentRepository departmentRepository;
    private final ApplicationEventPublisher publisher;
    private final TreeNodeRepository treeNodeRepository;
    private final RoleRepository roleRepository;
    private final UserRepository userRepository;
    private final DepartmentLinkmanMpRepository departmentLinkmanMpRepository;

    public DepartmentServiceImpl(DepartmentRepository departmentRepository, ApplicationEventPublisher publisher, TreeNodeRepository treeNodeRepository, RoleRepository roleRepository, UserRepository userRepository, DepartmentLinkmanMpRepository departmentLinkmanMpRepository) {
        this.departmentRepository = departmentRepository;
        this.publisher = publisher;
        this.treeNodeRepository = treeNodeRepository;
        this.roleRepository = roleRepository;
        this.userRepository = userRepository;
        this.departmentLinkmanMpRepository = departmentLinkmanMpRepository;
    }


    /**
     * 创建部门
     *
     * @param param
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createDepartment(CreateDepartmentParam param) {
        //获取上级部门信息
        Long parentId = param.getParentId();
        Long tenantId = FinalValue.TOP_TENANT_ID;

        Department parent = null;
        if (parentId == null) {
            parentId = FinalValue.TOP_DEPARTMENT_ID;
        }
        //如果没有上级id的话，则做为顶级部门的下级
        parent = departmentRepository.getByIdCheck(parentId);
        int level = parent.getLevel() + 1;

        if (level >= 3) {
            throw new BizException("部门层级不能过3级");
        }

        Department department = new Department();
        BeanUtils.copyProperties(param, department);

        //继承上级部门的信息，等级加1
        department.setLevel(level);
        department.setTenantId(tenantId);
        department.setParentId(parentId);
        Long id = IdGenerator.SNOW.generate();
        department.setId(id);
        department.setIsDisable(!param.getEnabled());

        departmentRepository.create(department);

        //发送创建部门事件
        CreateDepartmentEvent event = new CreateDepartmentEvent();
        event.setId(id);
        event.setParentId(parentId);
        publisher.publishEvent(event);
    }

    /**
     * 修改部门
     *
     * @param param
     */
    @Override
    public void editDepartment(EditDepartmentParam param) {
        Long id = param.getId();
        Department department = departmentRepository.getByIdCheck(id);
        BeanUtils.copyProperties(param, department);
        department.setIsDisable(!param.getEnabled());

        department.setParentId(null);
        departmentRepository.edit(department);
    }

    /**
     * 移除部门
     *
     * @param id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeDepartment(Long id) {
        departmentRepository.getByIdCheck(id);
        departmentRepository.removeById(id);

        //检查子部门
        List<Department> departments = departmentRepository.getBaseMapper().selectList(new LambdaQueryWrapper<Department>()
                .eq(Department::getParentId, id)
                .eq(Department::getIsDelete, false)
        );
        if (CollectionUtil.isNotEmpty(departments)){
            throw new BizException("请先删除部门下的子部门");
        }

        //检查角色
        List<Role> roles = roleRepository.getBaseMapper().selectList(new LambdaQueryWrapper<Role>()
                .eq(Role::getDepartmentId, id)
                .eq(Role::getIsDelete, false));
        if (CollectionUtil.isNotEmpty(roles)){
            throw new BizException("请先删除部门下的角色");
        }

        //检查用户
        List<User> users = userRepository.getBaseMapper().selectList(new LambdaQueryWrapper<User>()
                .eq(User::getDepartmentId, id)
                .eq(User::getIsDelete, false));
        if (CollectionUtil.isNotEmpty(users)){
            throw new BizException("请先删除部门下的用户");
        }
    }

    /**
     * 启动/禁用部门
     *
     * @param id
     */
    @Override
    public void enabledDepartment(Long id) {
        Department department = departmentRepository.getByIdCheck(id);
        department.setIsDisable(!department.getIsDisable());
        departmentRepository.edit(department);
    }

    /**
     * 获取部门详情
     *
     * @param id
     * @return
     */
    @Override
    public GetDepartmentVo getDepartment(Long id) {
        Department department = departmentRepository.getByIdCheck(id);
        GetDepartmentVo vo = new GetDepartmentVo();
        BeanUtils.copyProperties(department, vo);

        vo.setEnabled(!department.getIsDisable());
        return vo;
    }

    /**
     * 获取部门 列表
     *
     * @param param
     * @return
     */
    @Override
    public PageResult<GetDepartmentListVo> getDepartmentList(GetDepartmentListParam param) {

        SelectDepartmentDto dto = new SelectDepartmentDto();
        BeanUtils.copyProperties(param, dto);
        Page<Department> page = departmentRepository.selectDepartment(dto);
        List<Department> departmentList = page.getRecords();
        List<GetDepartmentListVo> list = new ArrayList<>();
        for (Department department : departmentList) {
            GetDepartmentListVo vo = new GetDepartmentListVo();
            BeanUtils.copyProperties(department, vo);

            list.add(vo);
        }
        return new PageResult<>(list, page);
    }

    /**
     * 获取部门下拉列表
     *
     * @param param
     * @return
     */
    @Override
    public List<GetDepartmentDownListVo> getDepartmentDownList(GetDepartmentDownListParam param) {
        Department po = new Department();
        if (param != null) {
            BeanUtils.copyProperties(param, po);
        }
        List<Department> departmentList = departmentRepository.getListByEntity(po);

        List<GetDepartmentDownListVo> list = new ArrayList<>();
        for (Department department : departmentList) {
            GetDepartmentDownListVo vo = new GetDepartmentDownListVo();
            BeanUtils.copyProperties(department, vo);
            vo.setEnabled(!department.getIsDisable());
            list.add(vo);
        }
        return list;
    }

    /**
     * 设置部门负责人
     *
     * @param param
     */
    @Override
    public void setDepartmentLinkman(SetDepartmentLinkmanParam param) {
        Long id = param.getId();
        departmentRepository.getByIdCheck(id);
        departmentLinkmanMpRepository.clean(id);
        List<Long> linkmanIds = param.getLinkmanIds();
        int userSize = userRepository.getListByIds(linkmanIds).size();
        if (linkmanIds.size()!=userSize){
            throw new BizException("用户错误");
        }

        List<DepartmentLinkmanMp> mpList = new ArrayList<>();

        for (Long linkmanId : linkmanIds) {
            DepartmentLinkmanMp mp=new DepartmentLinkmanMp();
            mp.setId(IdGenerator.SNOW.generate());
            mp.setDepartmentId(id);
            mp.setUserId(linkmanId);

            mpList.add(mp);
        }

        departmentLinkmanMpRepository.saveBatch(mpList);
    }

    /**
     * 创建顶级部门
     *
     * @param dto
     * @return
     */
    @Override
    public void createTopDepartment(CreateTopDepartmentDto dto) {
        Department department = new Department();
        BeanUtils.copyProperties(dto, department);

        Long departmentId = dto.getDepartmentId();
        department.setId(departmentId);
        department.setLevel(0);
        department.setParentId(0L);
        department.setRemark("top department");

        departmentRepository.create(department);


        //发送创建部门事件

        CreateDepartmentEvent event = new CreateDepartmentEvent();
        event.setId(departmentId);
        publisher.publishEvent(event);
    }

    /**
     * 编辑企业顶级部门
     *
     * @param dto
     */
    @Override
    public void editTopDepartment(EditTopDepartmentDto dto) {
        Long tenantId = dto.getTenantId();
        Department topDepartment = departmentRepository.getTopDepartment(tenantId);
        if (topDepartment == null) {
            throw new BizException("部门未找到");
        }


        topDepartment.setName(dto.getName());

        departmentRepository.edit(topDepartment);

    }

    /**
     * 批量删除部门
     *
     * @param idList
     */
    @Override
    public void bathRemoveDepartment(List<Long> idList) {
        departmentRepository.bathRemoveDepartment(idList);
    }


}



